#ifndef SeqColl_First
#define SeqColl_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Collection.h"

extern char *cNotLegalIndex;
extern char *cNotLegalIndex0;

//---- abstract class SeqCollection (sequencable collection) -------------------
//     sequenceable collections have an ordering relation, e.g. there is a first
//     and last element

class SeqCollection: public Collection {
protected:
	SeqCollection();
public:
	MetaDef(SeqCollection);

	Object *Add(Object *op);
	virtual Object *AddFirst(Object *op);
	virtual Object *AddLast(Object *op);
	virtual Object *AddAt(Object *op, int idx);
	virtual Object *AddBefore(Object *op, Object *after);
	virtual Object *AddBeforePtr(Object *op, Object *after);
	virtual Object *AddAfter(Object *op, Object *before);
	virtual Object *AddAfterPtr(Object *op, Object *before);
	virtual Object *PutAt(Object *op, int idx);
	Object *Remove(Object *op);
	Object *RemovePtr(Object *op);
	virtual Object *RemoveFirst();
	virtual Object *RemoveLast();
	virtual Object *RemoveAt(int i);
	virtual Object *RemoveBefore(Object *after);
	virtual Object *RemoveBeforePtr(Object *after);
	virtual Object *RemoveAfter(Object *before);
	virtual Object *RemoveAfterPtr(Object *before);

	//---- accessing
	Object *Find(Object *op);
	Object *FindPtr(Object *op);

	virtual Object *At(int i);
	virtual Object *Before(Object *);
	virtual Object *BeforePtr(Object *);
	virtual Object *After(Object *);
	virtual Object *AfterPtr(Object *);
	virtual Object *First();
	virtual Object *Last();
	int LastIndex();
	virtual int IndexOf(Object *op);    // returns -1 if not found, uses IsEqual
	virtual int IndexOfPtr(Object *op); // returns -1 if not found, uses identity
	Object *AnyElement();               // returns the first element if any
protected:
	//---- implementation
	bool NotLegalIndex(char *method, int i);    // check index i
	bool NotLegalIndex0(char *method, int i);   // check index i

	//---- primitives
	virtual Object *primAddAt(Object *op, int idx);
	virtual Object *primRemoveAt(int idx);
	virtual Object *primPutAt(Object *op, int idx);
	virtual Object *primAt(int idx);
	virtual Object *primIndexOf(Object *op, int offset, int *start);
	virtual Object *primIndexOfPtr(Object *op, int offset, int *start);
	virtual Object *AddRelative(Object *op, EqualType eq, int offset, Object *to);
	virtual Object *RemoveRelative(Object *op, EqualType eq, int offset);

	//---- misc
	void RemoveDeleted();
	static int CompareFun(void *, void *);      // for qsort
};

//---- SeqCollection inlines ---------------------------------------------------

inline int SeqCollection::LastIndex()
	{ return Size() - 1; }

inline bool SeqCollection::NotLegalIndex(char *method, int i)
	{ return (i >= 0) && (i < size)
					? FALSE
					: (Error(method, cNotLegalIndex, i, size), TRUE); }

inline bool SeqCollection::NotLegalIndex0(char *method, int i)
	{ return (i >= 0) && (i <= size)
					? FALSE
					: (Error(method, cNotLegalIndex0, i, size), TRUE); }

#endif

